package com.ideaction.game.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.ideaction.game.utils.ac.AhoCorasick;
import com.ideaction.game.utils.ac.SearchResult;

import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SensitiveWords {
	/** 零长度字节数组 */
	public static final byte[] EMPTY = {};
	public static String REPLACE_STR = "*";

	/**
	 * 检测敏感词的时候, 需要先清除的字符
	 */
	public static String[] IGNORESTRS = { " ", "&" };

	/**
	 * 检查角色名的正则表达式
	 */
	public static Pattern p = Pattern.compile("[\\\\;:~`!@#%&()={}|'<>,/\\$\\^\\*\\+\\?\"\\[\\]，。、？：；”“]");

	/**
	 * 检查网址正则表达式
	 */
	public static String urlRegex = "(((https|http)?://)?([a-z0-9]+[.])|(www.))\\w+[.|\\/]([a-z0-9]{0,})?[[.]([a-z0-9]{0,})]+((/[\\S&&[^,;\u4E00-\u9FA5]]+)+)?([.][a-z0-9]{0,}+|/?)";
	/**
	 * 检查表情正则表达式
	 */
	public static Pattern emoji = Pattern.compile(
			"[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]",
			Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);
	private static SensitiveWords sensitiveWords;

	public static SensitiveWords getInstance() {
		if (sensitiveWords == null)
			sensitiveWords = new SensitiveWords();
		return sensitiveWords;
	}

	/**
	 * 敏感字过滤器
	 */
	private static AhoCorasick ahoCorasick;
	/**
	 * 初始化ac
	 */
	public static void initAC(String sensitiveConfig) {
		try {
			log.info(" init sensitive words...");
			File file = new File(sensitiveConfig);
			if (!file.exists()) {
				log.warn(" init ac err. file is null. fileName=" + sensitiveConfig);
				return;
			}
			String allWorlds = read(file, "UTF-8");
			String[] keywords = allWorlds.split(",");
			AhoCorasick tree = new AhoCorasick();
			int length = keywords.length;
			for (int i = 0; i < length; i++) {
				if (keywords[i].trim().length() != 0) {
					tree.add(keywords[i].trim().getBytes(), keywords[i].trim());
				}
			}
			tree.prepare();
			ahoCorasick = tree;
		} catch (Exception e) {
			log.warn(" init ac err.", e);
		}
	}

	/**
	 * 敏感字过滤
	 *
	 * @param content
	 *            内容
	 * @return 返回过滤之后的内容
	 */
	public static String replaceInvalid(String content) {
		if (ahoCorasick == null) {
			log.warn(" replace invalid err. ahoCorasick is null.");
			return content;
		}
		String str = content.trim().toLowerCase();
		for (int i = 0; i < IGNORESTRS.length; i++) {
			str = str.replaceAll(IGNORESTRS[i], "");
		}
		Set<String> invalidSet = new HashSet<String>();
		Iterator<Object> iter = ahoCorasick.search(str.getBytes());
		SearchResult result = null;
		while (iter.hasNext()) {
			result = (SearchResult) iter.next();
			invalidSet.addAll(result.getOutputs());
		}
		if (invalidSet.size() > 0) {
			for (Iterator<String> iterator = invalidSet.iterator(); iterator.hasNext();) {
				String invalidStr = (String) iterator.next();
				str = str.replaceAll(invalidStr, REPLACE_STR);
			}
			return str;
		}
		return content;
	}

	/**
	 * 检查是否有敏感词
	 *
	 * @param content
	 *            内容
	 * @return 返回是否有敏感词, true有, false没有
	 */
	public static boolean checkInvalid(String content) {
		if (ahoCorasick == null) {
			log.warn(" check invalid err. ahoCorasick is null.");
			return true;
		}
		String str = content.trim().toLowerCase();
		if(str.isEmpty()){
			return true;
		}
		for (int i = 0; i < IGNORESTRS.length; i++) {
			str = str.replaceAll(IGNORESTRS[i], "");
		}
		Iterator<Object> iter = null;
		try {
			iter = ahoCorasick.search(str.getBytes("UTF-8"));
		} catch (UnsupportedEncodingException e) {
			log.warn(" checkInvalid get Code error content=" + content, e);
			return false;
		}
		return iter.hasNext();
	}

	/**
	 * 是否包含有非法字符
	 */
	public static boolean checkInvalidChars(String content) {
		Matcher m = p.matcher(content);
		// 如果没有非法字符
		if (!m.find()) {
			char[] cs = content.toCharArray();
			for (int i = 0; i < cs.length; i++) {
				String hs = Integer.toHexString(cs[i]);
				if (hs.equals("d83c") || hs.equals("df45")) {
					return true;
				}
			}
			return /* TextKit.isHavaEmoji(content) */false;
		} else {
			return true;
		}
	}

	/**
	 * 检查是否包含网址
	 *
	 * @param content
	 * @return
	 */
	public static boolean checkContainUrl(String content) {
		if (content == null || content.trim().isEmpty()) {
			return false;
		}
		Pattern pat = Pattern.compile(urlRegex.trim());// 比对
		Matcher mat = pat.matcher(content.trim());
		return mat.matches();
	}

	/**
	 * 将网址替换成指定包含网址的内容替换成指定内容的字符串
	 *
	 * @param content
	 *            要检查的内容
	 * @param replacement
	 *            网址部分需要替换成的内容
	 */
	public static String replaceUrl(String content, String replacement) {
		if (content == null || content.trim().isEmpty()) {
			return "";
		}
		if (replacement == null) {
			return content;
		}
		return content.replaceAll(urlRegex.trim(), replacement);
	}

	/**
	 * 是否含有表情
	 *
	 * @param source
	 * @return
	 */
	public static boolean filterEmoji(String source) {
		try {
			if (source != null) {
				Matcher emojiMatcher = emoji.matcher(source);
				if (emojiMatcher.find()) {
					return true;
				}
				return false;
			}
		} catch (Exception e) {
		}
		return false;
	}
	public static String read(File file, String encoding) {
		String string = "";
		try {
			BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), encoding));
			String str = "";
			while ((str = in.readLine()) != null) {
				string += str + "\r\n";
			}
			in.close();
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return string;
	}
}
